package net.aiotos.common.util;

import com.alibaba.fastjson.JSONObject;
import com.beust.jcommander.ParameterException;
import lombok.extern.slf4j.Slf4j;
import net.aiotos.common.dto.IotosYmlConfig;
import net.aiotos.common.dto.LoginDTO;
import org.yaml.snakeyaml.Yaml;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.Map;


/**
 * 命令行工具
 */
@Slf4j
public class Command {

    public final static String CERT_DIR_NAME = "certs";
    public final String runDir;
    public final String certDir;
    IotosYmlConfig.IotosService argsParser;
    public final String[] args;

    public <T> Command(Class<T> tClass, String[] args) throws NoSuchMethodException {
        this.args = args;
        String runDir = getRunDir(tClass);
        this.runDir = runDir;
        log.info("运行目录：{}", this.runDir);
        this.certDir = this.runDir + File.separator + CERT_DIR_NAME;
        log.info("证书目录：{}", this.certDir);
    }

    /**
     * 判断是不是用jar运行程序
     * @param path 当前运行文件名
     * @return
     */
    private static boolean isJarRun(String path) {
        return path.toLowerCase().endsWith(".jar");
    }

    public static ArgsParser argsParser(String[] args) throws Exception {
        return new ArgsParser().parse(args);
    }

    /**
     *
     * @param tClass 传入的必须是执行入口炎（Main.main）
     * @param <T>
     * @return
     */
    public static <T> String getRunDir(Class<T> tClass) throws NoSuchMethodException {
        Method[] methods = tClass.getMethods();
        boolean hasMain = false;
        for (Method method : methods) {
            if(method.getName().equals("main")) {
                hasMain = true;
                continue;
            }
        }
        if(hasMain == false) {
            throw new NoSuchMethodException(String.format("%s:不存在执行入口main方法", tClass.getName()));
        }
        String currentPath = tClass.getProtectionDomain().getCodeSource().getLocation().getFile();
        String run_dir = null;
        if(isJarRun(currentPath)) {
            String[] paths = currentPath.split("/");
            run_dir = currentPath.replace("/" + paths[paths.length - 1], "");
        } else {
            run_dir = System.getProperty("user.dir");
        }

        return run_dir;

    }

    public IotosYmlConfig.IotosService getArgsParser() throws Exception {
        ArgsParser argsParser = null;
        try {
            argsParser = argsParser(args);
            IotosYmlConfig.IotosService iotosService = new IotosYmlConfig.IotosService();
            iotosService.setHost(argsParser.getHost());
            iotosService.setUsername(argsParser.getUsername());
            iotosService.setPassword(argsParser.getPassword());
            iotosService.setUuid(argsParser.getUuid());
            return iotosService;
        } catch (ParameterException parameterException) {

        }
        File ymlFile = new File(this.runDir + "/iotos.yml");
        if(!(ymlFile.exists() && ymlFile.isFile())) {
            if(argsParser != null) {
                argsParser.getUsage();
            }
            throw new Exception("iotos.yml配置运行配置文件不存在或者请使用命令行参数");
        }
        if(!ymlFile.canRead()) {
            throw new Exception("iotos.yml不可读，请设置文件操作权限");
        }
        FileReader fileReader = new FileReader(ymlFile);
        Reader reader = new BufferedReader(fileReader);


        Yaml yaml = new Yaml();
        JSONObject ymlJson = yaml.loadAs(fileReader, JSONObject.class);
        IotosYmlConfig iotosYmlConfig = new IotosYmlConfig();
        iotosYmlConfig.setVersion(ymlJson.getFloat("version"));
        iotosYmlConfig.setEnv(ymlJson.getString("env"));

        ymlJson.remove("version");
        ymlJson.remove("env");

        IotosYmlConfig.IotosService iotosService = null;
        for (Map.Entry<String, Object> entry : ymlJson.entrySet()) {
            iotosService = ymlJson.getJSONObject(entry.getKey()).toJavaObject(IotosYmlConfig.IotosService.class);
            iotosYmlConfig.getServices().put(entry.getKey(), iotosService);
        }

        if(iotosYmlConfig.getServices().size() != 1) {
            if(iotosYmlConfig.getEnv() != null && iotosYmlConfig.getServices().containsKey(iotosYmlConfig.getEnv())) {
                iotosService = iotosYmlConfig.getServices().get(iotosYmlConfig.getEnv());
            } else if(!iotosYmlConfig.getServices().containsKey("default")) {
                throw new NotImplementedException();
            } else {
                iotosService = iotosYmlConfig.getServices().get("default");
            }
        }
        return iotosService;
    }

    /**
     * 获取命令行登录参数
     * @return
     * @throws Exception
     */
    public LoginDTO getWebLoginParam() throws Exception {
        IotosYmlConfig.IotosService argsParser = getArgsParser();
        return new LoginDTO(argsParser.getUsername(), argsParser.getPassword(), argsParser
                .getUuid(), argsParser.getHost(), certDir);
    }
}
